package net.xdclass.config;

import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Paths;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springdoc.core.GroupedOpenApi;
import org.springdoc.core.customizers.OpenApiCustomiser;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;


import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RequiredArgsConstructor
@Configuration
@ConditionalOnClass({OpenAPI.class})
@ConditionalOnProperty(prefix = "springdoc.api-docs", name = "enabled", havingValue = "true", matchIfMissing = true)
// 设置为 false 时，禁用
public class SpringDocConfig {

    private final ServerProperties serverProperties;

    @Bean
    public OpenAPI createApi() {
        Map<String, SecurityScheme> securitySchemas = buildSecuritySchemes();
        OpenAPI openAPI = new OpenAPI()
                .info(convertInfo())
                // 接口安全配置
                .components(new Components().securitySchemes(securitySchemas));
        securitySchemas.keySet().forEach(key -> openAPI.addSecurityItem(new SecurityRequirement().addList(key)));
        return openAPI;
    }

    private Info convertInfo() {
        Info info = new Info();
        info.setTitle("标题：1024程序员节");
        info.setDescription("描述：用于服务");
        info.setContact(new Contact().name("flyrun").email("1106177694@qq.com").url(""));
        info.setLicense(new License());
        info.setVersion("版本号: 1.0.0");
        return info;
    }

    @Bean
    public GroupedOpenApi publicApi() {
        return GroupedOpenApi.builder()
                .group("用户端")
                .pathsToMatch("/api/**")
                .build();
    }

    @Bean
    public GroupedOpenApi adminApi() {
        return GroupedOpenApi.builder()
                .group("管理端")
                .pathsToMatch("/admin/**")
                .build();
    }

    /**
     * 安全模式，这里配置通过请求头 Authorization 传递 token 参数
     */
    private Map<String, SecurityScheme> buildSecuritySchemes() {
        Map<String, SecurityScheme> securitySchemes = new HashMap<>();
        SecurityScheme securityScheme = new SecurityScheme()
                .type(SecurityScheme.Type.APIKEY) // 类型
                .name(HttpHeaders.AUTHORIZATION) // 请求头的 name
                .in(SecurityScheme.In.HEADER); // token 所在位置
        securitySchemes.put(HttpHeaders.AUTHORIZATION, securityScheme);
        return securitySchemes;
    }


//    /**
//     * 对已经生成好的 OpenApi 进行自定义操作
//     */
//    @Bean
//    public OpenApiCustomiser openApiCustomiser() {
//        String contextPath = serverProperties.getServlet().getContextPath();
//        String finalContextPath;
//        if (StringUtils.isBlank(contextPath) || "/".equals(contextPath)) {
//            finalContextPath = "";
//        } else {
//            finalContextPath = contextPath;
//        }
//        // 对所有路径增加前置上下文路径
//        return openApi -> {
//            Paths oldPaths = openApi.getPaths();
//            if (oldPaths instanceof PlusPaths) {
//                return;
//            }
//            PlusPaths newPaths = new PlusPaths();
//            oldPaths.forEach((k,v) -> newPaths.addPathItem(finalContextPath + k, v));
//            openApi.setPaths(newPaths);
//        };
//    }
//
//    /**
//     * 单独使用一个类便于判断 解决springdoc路径拼接重复问题
//     *
//     * @author Lion Li
//     */
//    static class PlusPaths extends Paths {
//
//        public PlusPaths() {
//            super();
//        }
//    }
}
